import {resources, TextAsset} from "cc";
import {CSV} from "./CSV";
import {CSVPaths} from "db://assets/scripts/common/CSVPaths";
import {CSVParser} from "db://assets/scripts/common/CSVParser";
import {SDKUtils} from "db://assets/scripts/utils/SDKUtils";
import {Constants} from "db://assets/scripts/common/Constants";

/**
 * CSV管理器
 * 可以把CSV看作一张表
 */
export class CSVManager {
    /**
     * CSV数据缓存
     */
    private tables: Map<string, CSV> = new Map<string, CSV>();

    /**
     * CSV管理器实例
     */
    private static INSTANCE: CSVManager;

    /**
     * 获取CSV管理器实例
     */
    public static getInstance(): CSVManager {
        // 当CSV管理器实例已存在时
        if (this.INSTANCE) {
            // 返回CSV管理器实例
            return this.INSTANCE;
        }
        // 初始化CSV管理器实例
        this.INSTANCE = new CSVManager();
        // 返回CSV管理器实例
        return this.INSTANCE;
    }

    private constructor() {
        // 初始化
        this.init();
    }

    /**
     * 初始化
     */
    private init() {
        // 初始化所有数据表
        resources.loadDir<TextAsset>("datas", TextAsset, (err, datas) => {
            if (err) {
                console.log(err);
                return;
            }

            datas.forEach(data => {
                let csv = CSVParser.parseToCSV(data.text, 3);
                CSVManager.getInstance().addCSV(CSVPaths.get(data.name), csv);
            });

            // 分享游戏
            SDKUtils.shareGame(Constants.GAME_NAME_CH, "");
        });
    }

    /**
     * 缓存CSV数据
     *
     * @param name 缓存名称
     * @param csv CSV数据
     */
    public addCSV(name: string, csv: CSV) {
        // 当缓存已存在时
        if (this.tables.has(name)) {
            return;
        }

        this.tables.set(name, csv);
    }

    /**
     * 根据名称获取数据
     *
     * @param name 缓存名称
     */
    public getTable(name: string): CSV {
        let result: CSV = {header: [], headerLength: 0, datas: []};
        if (this.tables.has(name)) {
            result = this.tables.get(name);
        }
        return result;
    }

    /**
     * 查询一行数据
     * 1.找到缓存表
     * 2.找到列名（根据ID查询还是根据名称查询）
     * 3.找到与目标值相匹配那一行
     *
     * @param path 表路径
     * @param column 列名
     * @param key 目标值
     */
    public getRowDatas(path: string, column: string, key: string): string[] {
        // 结果
        let result: string[] = [];

        // 当表不存在时
        if (!this.tables.has(path)) {
            return result;
        }

        // 获取表
        let table = this.tables.get(path);

        // 获取指定列的索引
        let index = this.getColumnIndex(table, column);
        // 当索引不存在时
        if (index === -1) {
            return result;
        }

        // 遍历表中所有数据
        for (let row of table.datas) {
            // 匹配每一行的数据
            if (row[index] === key) {
                // 找到目标行
                result = row;
                // 结束循环
                break;
            }
        }

        // 返回结果
        return result;
    }

    /**
     * 查询一列数据
     *
     * @param path 表路径
     * @param column 列名
     */
    public getColumnDatas(path: string, column: string): string[] {
        // 结果
        let result: string[] = [];

        // 当表不存在时
        if (!this.tables.has(path)) {
            return result;
        }

        // 获取表
        let table = this.tables.get(path);

        // 获取指定列的索引
        let index = this.getColumnIndex(table, column);
        // 当索引不存在时
        if (index === -1) {
            return result;
        }

        // 遍历表中所有数据
        for (let row of table.datas) {
            // 将指定列的值添加至结果集中
            result.push(row[index]);
        }

        // 返回结果
        return result;
    }

    /**
     * 寻找CSV列的索引
     *
     * @param table CSV表
     * @param column 列
     */
    private getColumnIndex(table: CSV, column: string): number {
        // 当缓存为空时
        if (!table) {
            return -1;
        }
        // 获取CSV信息
        let index: number = -1;
        for (let headerRow of table.header) {
            // 列的索引
            index = headerRow.indexOf(column);
            if (index !== -1) {
                break;
            }
        }
        return index;
    }
}